import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios'
import { ElMessage } from 'element-plus'
import { useUserStore } from '@/stores'
import router from '@/routers'

export interface ApiResponse<T = any> {
  code: number
  data: T
  message: string
  success: boolean
}

const config = {
  baseURL: import.meta.env.VITE_API_URL || '/api',
  timeout: 10000,
  withCredentials: true,
}

class RequestHttp {
  service: AxiosInstance
  
  constructor(config: AxiosRequestConfig) {
    this.service = axios.create(config)

    this.service.interceptors.request.use(
      (config: AxiosRequestConfig) => {
        const userStore = useUserStore()
        
        if (userStore.token) {
          config.headers = {
            ...config.headers,
            Authorization: `Bearer ${userStore.token}`
          }
        }

        config.headers = {
          ...config.headers,
          'Content-Type': 'application/json'
        }

        return config
      },
      (error: AxiosError) => {
        return Promise.reject(error)
      }
    )

    this.service.interceptors.response.use(
      (response: AxiosResponse<ApiResponse>) => {
        const { data } = response
        
        if (data.code === 200 || data.success) {
          return data
        }
        
        ElMessage.error(data.message || '请求失败')
        return Promise.reject(data)
      },
      (error: AxiosError<ApiResponse>) => {
        const { response } = error
        
        if (response) {
          const { status, data } = response
          
          switch (status) {
            case 401:
              ElMessage.error('登录已过期，请重新登录')
              const userStore = useUserStore()
              userStore.logout()
              router.push('/login')
              break
            case 403:
              ElMessage.error('没有权限访问该资源')
              break
            case 404:
              ElMessage.error('请求的资源不存在')
              break
            case 500:
              ElMessage.error('服务器内部错误')
              break
            default:
              ElMessage.error(data?.message || '网络错误')
          }
        } else {
          ElMessage.error('网络连接失败')
        }
        
        return Promise.reject(error)
      }
    )
  }

  get<T = any>(url: string, params?: object, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return this.service.get(url, { params, ...config })
  }

  post<T = any>(url: string, data?: object, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return this.service.post(url, data, config)
  }

  put<T = any>(url: string, data?: object, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return this.service.put(url, data, config)
  }

  delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return this.service.delete(url, config)
  }

  upload<T = any>(url: string, file: File, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    const formData = new FormData()
    formData.append('file', file)
    
    return this.service.post(url, formData, {
      ...config,
      headers: {
        'Content-Type': 'multipart/form-data',
        ...config?.headers
      }
    })
  }
}

export default new RequestHttp(config)